/*
 ============================================================================
 Name		: CPanicSession.cpp
 Author	  : wangli@opi-corp.com
 Version	 : 1.0
 Copyright   : Your copyright notice
 Description : CCPanicSession implementation
 ============================================================================
 */

#include "CPanicSession.h"
#include "Service.h"
#include <UTF.H>

_LIT(KDumpPath, "C:\\DATA\\PanicServer\\");
_LIT(PanicDescription, "PanicServer");
static void PanicClient(TInt aCode, const RMessage2& aMessage)
{
    aMessage.Panic(PanicDescription, aCode);
}

CPanicSession::CPanicSession()
    :iClosed(EFalse)
{
}

CPanicSession::~CPanicSession()
{
    /**
     * 如果未关闭但是PanicSession被析构，
     * 说明应该是Panic造成的
     */
    if(!iClosed)
    {
        TInt reason = iClientThread.ExitReason();
        TExitCategoryName category = iClientThread.ExitCategory();
        TBuf8<KMaxExitCategoryName + 16> buf;
        buf.Append(_L8("Client Exit("));
        buf.Append(category);
        buf.Append(_L8(" "));
        buf.AppendNum(reason);
        buf.Append(_L8(")"));
        MakeRecord(buf);
    }
    
    iClientThread.Close();
    iStack.Close();
    iDumpFile.Close();
    iFs.Close();
}

CPanicSession* CPanicSession::NewLC(const RMessage2& aMessage)
{
    CPanicSession* self = new (ELeave) CPanicSession();
    CleanupStack::PushL(self);
    self->ConstructL(aMessage);
    return self;
}

CPanicSession* CPanicSession::NewL(const RMessage2& aMessage)
{
    CPanicSession* self = CPanicSession::NewLC(aMessage);
    CleanupStack::Pop(); 
    return self;
}

void CPanicSession::ConstructL(const RMessage2& aMessage)
{
    aMessage.ClientL(iClientThread, EOwnerProcess);
}

void CPanicSession::ServiceL(const RMessage2& aMessage)
{
    TRAPD(err, DispatchMessageL(aMessage));
    if(KErrNone != err)
    {
        RDebug::Printf("DispatchMessageL error:%d", err);
        aMessage.Complete(err);
    }
}

void CPanicSession::DispatchMessageL(const RMessage2& aMessage)
{
    switch(aMessage.Function())
    {
    case ECreateStack:{
        CreateCallStack(aMessage);
        return ;
    } break;
    case EClientLeave:{
        ClientLeaveService(aMessage);
        return ;
    } break;
    case ECloseSession:{
        CloseSession(aMessage);
        return ;
    } break;
    default:{
        PanicClient(KErrRequestType, aMessage);
    } break;
    }
}

void CPanicSession::CreateCallStack(const RMessage2& aMessage)
{
    if(iStack.IsAvaliable())
    {
        PanicClient(KErrCreateStackRepeat, aMessage);
        iStack.Close();
        return ;
    }
    
    TFullName stackName;
    TRAPD(err, aMessage.ReadL(0, stackName));
    TInt stackSize = aMessage.Int1();
    if(err != KErrNone || stackSize <= 0)
    {
        PanicClient(KErrRequestParam, aMessage);
        return ;
    }
    
   TRAP(err, iStack.CreateL(stackName, stackSize));
   if(err != KErrNone)
   {
       aMessage.Complete(KErrCreateGlobalChunk);
       return ;
   }
   CleanupClosePushL(iStack);
   User::LeaveIfError(iFs.Connect());
   CleanupClosePushL(iFs);
   TFileName dumpFileName;
   dumpFileName.Append(KDumpPath);
   dumpFileName.Append(stackName);
   User::LeaveIfError(iDumpFile.Replace(iFs, dumpFileName, EFileWrite));
   CleanupStack::Pop(2, &iStack);
   
   aMessage.Complete(KErrNone);
}

void CPanicSession::ClientLeaveService(const RMessage2& aMessage)
{
    aMessage.Complete(MakeRecord(_L8("Client Leave")));
}

_LIT8(KComma, ":");
_LIT8(KSureReturn, "\r\n");
_LIT(KTimeFormat, "#<%F%Y-%M-%D %H:%T:%S>");
TInt CPanicSession::MakeRecord(const TDesC8& aInfo)
{
    TDesC* stackDescription = NULL;
    TRAPD(err, stackDescription = iStack.DumpL());
    if(err != KErrNone)
    {
        iDumpFile.Write(aInfo);
        iDumpFile.Write(KComma);
        iDumpFile.Write(_L8("Server MakeRecord leave"));
        iDumpFile.Write(KSureReturn);
        return err;
    }
        
    CleanupDeletePushL(stackDescription);
    HBufC8* utfbuf = CnvUtfConverter::ConvertFromUnicodeToUtf8L(*stackDescription);
    CleanupDeletePushL(utfbuf);
        
    TTime currentTime;
    currentTime.HomeTime();
    TBuf<32> timeBuf;
    currentTime.FormatL(timeBuf, KTimeFormat);
    TBuf8<32> timeBuf8;
    timeBuf8.Append(timeBuf);
        
    iDumpFile.Write(timeBuf8);
    iDumpFile.Write(aInfo);
    iDumpFile.Write(KComma);
    iDumpFile.Write(KSureReturn);
    iDumpFile.Write(*utfbuf);
    iDumpFile.Write(KSureReturn);
    iDumpFile.Flush();
    CleanupStack::PopAndDestroy(2, stackDescription);
    return KErrNone;
}

void CPanicSession::CloseSession(const RMessage2& aMessage)
{
    iStack.Close();
    iDumpFile.Write(_L8("===end====\r\n"));
    iDumpFile.Flush();
    iDumpFile.Close();
    iFs.Close();
    aMessage.Complete(KErrNone);
    iClosed = ETrue;
}




